我如何在博览会上上传照片



我正在制作一个带有博览会的应用程序,希望让用户拍照或从相机卷中挑选一张应用并将其上传到我的服务器。我该怎么做?

使用EXPO ImagePicker API显示相机或相机卷,并获取有关所选图像的信息:

async function takeAndUploadPhotoAsync() {
  // Display the camera to the user and wait for them to take a photo or to cancel
  // the action
  let result = await ImagePicker.launchCameraAsync({
    allowsEditing: true,
    aspect: [4, 3],
  });
  if (result.cancelled) {
    return;
  }
  // ImagePicker saves the taken photo to disk and returns a local URI to it
  let localUri = result.uri;
  let filename = localUri.split('/').pop();
  // Infer the type of the image
  let match = /.(w+)$/.exec(filename);
  let type = match ? `image/${match[1]}` : `image`;
  // Upload the image using the fetch and FormData APIs
  let formData = new FormData();
  // Assume "photo" is the name of the form field the server expects
  formData.append('photo', { uri: localUri, name: filename, type });
  return await fetch(YOUR_SERVER_URL, {
    method: 'POST',
    body: formData,
    headers: {
      'content-type': 'multipart/form-data',
    },
  });
}

有关包括服务器代码在内的更全面的示例,请参阅此回购:https://github.com/expo/image-upload-example。

官方示例使用node.js,以下是PHP:

expo

async function takePhotoAndUpload() {
  let result = await ImagePicker.launchCameraAsync({
    allowsEditing: false, // higher res on iOS
    aspect: [4, 3],
  });
  if (result.cancelled) {
    return;
  }
  let localUri = result.uri;
  let filename = localUri.split('/').pop();
  let match = /.(w+)$/.exec(filename);
  let type = match ? `image/${match[1]}` : `image`;
  let formData = new FormData();
  formData.append('photo', { uri: localUri, name: filename, type });
  return await fetch('http://example.com/upload.php', {
    method: 'POST',
    body: formData,
    header: {
      'content-type': 'multipart/form-data',
    },
  });
}

upload.php

<?php
    move_uploaded_file($_FILES['photo']['tmp_name'], './photos/' . $_FILES['photo']['name']);
?>
import React, { Component } from 'react';
import {
  ActivityIndicator,
  Button,
  Clipboard,
  Image,
  Share,
  StatusBar,
  StyleSheet,
  Text,
  TouchableOpacity,
  View,
} from 'react-native';
import { Constants } from 'expo';
import * as Permissions from 'expo-permissions';
import * as ImagePicker from 'expo-image-picker';
export default class App extends Component {
  state = {
    image: null,
    uploading: false,
  };
  render() {
    let {
      image
    } = this.state;
    return (
      <View style={styles.container}>
        <StatusBar barStyle="default" />
        <Text
          style={styles.exampleText}>
          Example: Upload ImagePicker result
        </Text>
        <Button
          onPress={this._pickImage}
          title="Pick an image from camera roll"
        />
        <Button onPress={this._takePhoto} title="Take a photo" />
        {this._maybeRenderImage()}
        {this._maybeRenderUploadingOverlay()}
      </View>
    );
  }
  _maybeRenderUploadingOverlay = () => {
    if (this.state.uploading) {
      return (
        <View
          style={[StyleSheet.absoluteFill, styles.maybeRenderUploading]}>
          <ActivityIndicator color="#fff" size="large" />
        </View>
      );
    }
  };
  _maybeRenderImage = () => {
    let {
      image
    } = this.state;
    if (!image) {
      return;
    }
    return (
      <View
        style={styles.maybeRenderContainer}>
        <View
          style={styles.maybeRenderImageContainer}>
          <Image source={{ uri: image }} style={styles.maybeRenderImage} />
        </View>
        <Text
          onPress={this._copyToClipboard}
          onLongPress={this._share}
          style={styles.maybeRenderImageText}>
          {image}
        </Text>
      </View>
    );
  };
  _share = () => {
    Share.share({
      message: this.state.image,
      title: 'Check out this photo',
      url: this.state.image,
    });
  };
  _copyToClipboard = () => {
    Clipboard.setString(this.state.image);
    alert('Copied image URL to clipboard');
  };
  _takePhoto = async () => {
    const {
      status: cameraPerm
    } = await Permissions.askAsync(Permissions.CAMERA);
    const {
      status: cameraRollPerm
    } = await Permissions.askAsync(Permissions.CAMERA_ROLL);
    // only if user allows permission to camera AND camera roll
    if (cameraPerm === 'granted' && cameraRollPerm === 'granted') {
      let pickerResult = await ImagePicker.launchCameraAsync({
        allowsEditing: true,
        aspect: [4, 3],
      });
      if (!pickerResult.cancelled) {
        this.setState({ image: pickerResult.uri });
      }
      this.uploadImageAsync(pickerResult.uri);
    }
  };
  _pickImage = async () => {
    const {
      status: cameraRollPerm
    } = await Permissions.askAsync(Permissions.CAMERA_ROLL);
    // only if user allows permission to camera roll
    if (cameraRollPerm === 'granted') {
      let pickerResult = await ImagePicker.launchImageLibraryAsync({
        allowsEditing: true,
        base64: true,
        aspect: [4, 3],
      });

      if (!pickerResult.cancelled) {
        this.setState({ image: pickerResult.uri});
      }
      this.uploadImageAsync(pickerResult.uri);
    }
  };
 uploadImageAsync(pictureuri) {
  let apiUrl = 'http://123.123.123.123/ABC';

    var data = new FormData();  
    data.append('file', {  
      uri: pictureuri,
      name: 'file',
      type: 'image/jpg'
    })
    fetch(apiUrl, {  
      headers: {
        'Accept': 'application/json',
        'Content-Type': 'multipart/form-data'
      },
      method: 'POST',
      body: data
    }).then(
      response => {
        console.log('succ ')
        console.log(response)
      }
      ).catch(err => {
      console.log('err ')
      console.log(err)
    } )


  }
}
const styles = StyleSheet.create({
  container: {
    alignItems: 'center',
    flex: 1,
    justifyContent: 'center',
  },
  exampleText: {
    fontSize: 20,
    marginBottom: 20,
    marginHorizontal: 15,
    textAlign: 'center',
  },
  maybeRenderUploading: {
    alignItems: 'center',
    backgroundColor: 'rgba(0,0,0,0.4)',
    justifyContent: 'center',
  },
  maybeRenderContainer: {
    borderRadius: 3,
    elevation: 2,
    marginTop: 30,
    shadowColor: 'rgba(0,0,0,1)',
    shadowOpacity: 0.2,
    shadowOffset: {
      height: 4,
      width: 4,
    },
    shadowRadius: 5,
    width: 250,
  },
  maybeRenderImageContainer: {
    borderTopLeftRadius: 3,
    borderTopRightRadius: 3,
    overflow: 'hidden',
  },
  maybeRenderImage: {
    height: 250,
    width: 250,
  },
  maybeRenderImageText: {
    paddingHorizontal: 10,
    paddingVertical: 10,
  }
});

对于博览会,除了使用Expo Filesystem uploadasync

之外,对我没有任何帮助
uploadImage = async ({ imageUri } }) => FileSystem.uploadAsync(
    apiUrl,
    imageUri,
    {
      headers: {
        // Auth etc
      },
      uploadType: FileSystem.FileSystemUploadType.MULTIPART,
      fieldName: 'files',
      mimeType: 'image/png',
    });

注意 - imageuri以file的格式:///mypath/to/image.png

由于所选的解决方案实际上对我不起作用,这是我制作的文件上传的方式与expo和django rest框架一起使用。

    const blobToBase64 = blob => {
      const reader = new FileReader();
      reader.readAsDataURL(blob);
      return new Promise(resolve => {
        reader.onloadend = () => {
          resolve(reader.result);
        };
      });
    };
    const formData = new FormData();
    const base64 = await blobToBase64(blob);
    formData.append('file', base64);
    formData.append('data', JSON.stringify(payload));  // additional data (I parse the string as json in the backend to get my payload back)
    // same code as chosen answer, this was not part of the problem
    return await fetch(YOUR_SERVER_URL, {
      method: 'POST',
      body: formData,
      headers: {
        'content-type': 'multipart/form-data',
      },
    });

在django中,我可以使用自定义解析器将base64字符串解码为字节,然后使用它创建一个SimpleUploadedFile对象。

    class MultipartJsonParser(parsers.MultiPartParser):
      def parse(self, stream, media_type=None, parser_context=None):
        result = super().parse(
            stream,
            media_type=media_type,
            parser_context=parser_context
        )
        base64_file = result.data.get('file')
        file_parts = base64_file.split(',')
        mime_type = re.sub(r'^data:([w/]+);base64$', '\1', file_parts[0])
        file = SimpleUploadedFile('file', base64.b64decode(file_parts[1]), mime_type)
        data = json.loads(result.data["data"]) or {}  # additional data sent by Expo app
        qdict = QueryDict('', mutable=True)
        qdict.update(data)
        return parsers.DataAndFiles(qdict, {'file': file})
    class MyUploadView(ModelViewSet):
      parser_classes = (MultipartJsonParser, parsers.JSONParser)
      def create(self, request, *args, **kwargs):
          # request.data should have a 'file' property with a SimpleUploadedFile object
          ...

,因为谁找不到或解决了这个问题。我花了三天的时间找到解决方案,我明白了。就我而言,这是数据对象的命名元素。Android版本10,Expo 4.11.0,

这是Front

async function uploadImage(uploadFile){
    const data = new FormData()
    data.append('name',{
        name: image_name, {/* name your image whatever you want*/}
        type: 'image/jpeg', {/* type of image that you're uploading*/}
        uri: uploadFile {/*data, file or image from ImagePicker here you should pass uri data but not all data from ImagePicker*/}
    })
{/*names of data object should be like this: name, type, uri*/}
    const response = await fetch(my_upload_api.php,{
        method: 'POST',
        body: data,
        headers: {
            'Content-Type': 'multipart/form-data'
        }
    })
}

这是PHP

上的后卫
if(!empty($_FILES['name']['name'])){
$target_dir = 'my folder where I put all images';
if(!file_exists($target_dir)){
    $data = array(
        (object)array(
            'code' => '400',
            'message' => 'Can't fined folder.'
        )
    );
    $json = json_encode($data);
    echo $json;
    die();
}
$target_file = $target_dir . basename($_FILES['name']['name']);
$image_file_type = pathinfo($target_file,PATHINFO_EXTENSION);
if(file_exists($target_file)){
    $data = array(
        (object)array(
            'code' => '400',
            'message' => 'Sorry. File already exists.'
        )
    );
    $json = json_encode($data);
    echo $json;
    die();
}
if($_FILES['name']['size'] > 50000000){
    $data = array(
        (object)array(
            'code' => '400',
            'message' => 'Sorry. Your file is too large.'
        )
    );
    $json = json_encode($data);
    echo $json;
    die();
}
if(move_uploaded_file($_FILES['name']['tmp_name'], $target_file)){
    $data = array(
        (object)array(
            'code' => '200',
            'message' => 'Successfuly your file has been uploaded.',
            'name' => $_FILES['name']
        )
    );
    $json = json_encode($data);
    echo $json;
    die();
}else{
    $data = array(
        (object)array(
            'code' => '400',
            'message' => 'Sorry. There was something wrong. Try it again.'
        )
    );
    $json = json_encode($data);
    echo $json;
    die();
}

}

这是我尝试找到解决方案的第一个博客。如果解决方案在这里,我也许会花费一段时间或更短的时间来解决这个问题。我希望我可以帮助某人。

相关内容

  • 没有找到相关文章

最新更新