React Native 用 axios 上传文件 PHP 后端接收不到,是二者之间传输协议问题吗? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Alucns
V2EX    问与答

React Native 用 axios 上传文件 PHP 后端接收不到,是二者之间传输协议问题吗?

  •  
  •   Alucns 2018-04-23 09:20:04 +08:00 5307 次点击
    这是一个创建于 2798 天前的主题,其中的信息可能已经有所发展或是发生改变。

    这坑好几天了没填满呀,我用 html 加载 axios 都可以上传,在 RN 里就不行了,有没有遇到类似问题的? HTML 写法

    var data = new FormData();

    data.append('avatar', $('#file')[0].files[0]);

    axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';

    axios.post('http://127.0.0.1//api/post/', data)

    .then(function (response) {

    console.log(response); 

    }) .catch(function (error) {

    console.log(error); 

    });

    });

    在 RN 里也是用 FormData 为么就不行?

    17 条回复    2018-04-24 09:55:47 +08:00
    swirling
        1
    swirling  
       2018-04-23 09:25:15 +08:00
    form data 是浏览器的 API. 你 RN 哪里有浏览器?
    Alucns
        2
    Alucns  
    OP
       2018-04-23 09:26:11 +08:00
    @swirling 请教一下,RN 有什么方式呀?
    Alucns
        3
    Alucns  
    OP
       2018-04-23 09:28:12 +08:00
    @swirling FormData 这个是构造虚拟表单,RN 应该支持吧。
    SourceMan
        4
    SourceMan  
       2018-04-23 09:30:26 +08:00   1
    帮你使用 Google 搜索了关键字 fetch file upload react native
    https://github.com/g6ling/React-Native-Tips/tree/master/How_to_upload_photo%2Cfile_in%20react-native
    这篇文章里有提到 new FormData();
    Pastsong
        5
    Pastsong  
       2018-04-23 09:34:59 +08:00 via Android
    form data 的 content type 不是 urlencode...
    Alucns
        6
    Alucns  
    OP
       2018-04-23 09:39:27 +08:00
    @Pastsong 用 application/octet-stream 和 multipart/form-data 都试过了都不行,PHP 后台接收不到
    chairuosen
        7
    chairuosen  
       2018-04-23 09:41:44 +08:00
    RN 能用 jQuery ?
    my101du
        8
    my101du  
       2018-04-23 09:46:38 +08:00
    在 html 里能上传,是指 post 数据到 http://127.0.0.1 正常,对吗?
    到 RN 里后端 php 接收不到数据,是不是因为 RN 编译成 app 后,http://127.0.0.1 是指向“这台手机 /模拟器”?
    wasabia
        9
    wasabia  
       2018-04-23 09:47:57 +08:00   1
    var xhr = new XMLHttpRequest();
    var url = "xxxx";
    xhr.open('POS', url);
    var formdata = new FormData();

    _.map(images, (image, index) => {
    formdata.append('photos[]', {type: "image/jpeg", name: 'image.jpg', uri: image.path});
    })

    xhr.Onload= () => {

    }
    xhr.send(formdata);
    Manweill
        10
    Manweill  
       2018-04-23 10:01:20 +08:00   1
    ['Content-Type']='multipart/form-data' 后台是可以收到的

    var formdata = new FormData();
    formdata.append('file', {type: "image/jpeg", name: 'image.jpg', uri: image.path});
    axios({url,formdata})
    Manweill
        11
    Manweill  
       2018-04-23 10:02:21 +08:00
    参数写错了,应该是这样

    var data = new FormData();
    formdata.append('file', {type: "image/jpeg", name: 'image.jpg', uri: image.path});
    axios({url,data})
    Alucns
        12
    Alucns  
    OP
       2018-04-23 10:02:54 +08:00
    @Manweill
    @wasabia
    谢谢!
    Alucns
        13
    Alucns  
    OP
       2018-04-23 10:03:56 +08:00
    @chairuosen 那个是网页测试的
    luwu1991
        14
    luwu1991  
       2018-04-23 10:53:27 +08:00 via iPhone
    抓包,看看 2 种情况下的上传请求有啥不同
    wentaoliang
        15
    wentaoliang  
       2018-04-23 12:48:29 +08:00
    为啥我印象中 axios 是 post 的是 json 的格式 php 要用 file://input 接收
    dilu
        16
    dilu  
       2018-04-23 21:46:31 +08:00   1
    我用的是 react-native-fetch-blob
    RN 中是这样写的
    ```
    handleSelectPhoto = () => {
    SYImagePicker.asyncShowImagePicker(options)
    .then(photos => {

    if(photos[0])//如果选择了图片
    {
    console.log('upload start');
    RNFetchBlob.fetch("POST",config.baseUrl + config.avatarUpload,{
    'Content-Type' : 'multipart/form-data',
    'token':user.password,
    'phone':user.teacher_phone,
    'isparent':0,
    },[
    {
    name:'file',
    filename:photos[0]['uri'],
    type:'image/jpg',
    data: RNFetchBlob.wrap(photos[0]['uri'])
    }
    ])
    .then((response) => response.json())
    .then((response) => {
    if(1 != response.code)
    {
    Toast.fail(response.msg);
    return false;
    }
    Toast.info(response.msg);
    this.setState({
    userAvatar:{uri:config.local + '/public' + response.data.url}
    });

    })
    .catch((err) => {
    console.log(err);
    Toast.fail('网络异常');
    })

    console.log(user);
    }
    })
    .catch(err => {

    })
    }
    ```

    后端是这样写的

    ```
    public function upload()
    {

    $file = $this->request->file('file');
    if (empty($file))
    {
    $this->error(__('No file upload or server upload limit exceeded'));
    }

    //判断是否已经存在附件
    $sha1 = $file->hash();

    $upload = Config::get('upload');

    preg_match('/(\d+)(\w+)/', $upload['maxsize'], $matches);
    $type = strtolower($matches[2]);
    $typeDict = ['b' => 0, 'k' => 1, 'kb' => 1, 'm' => 2, 'mb' => 2, 'gb' => 3, 'g' => 3];
    $size = (int) $upload['maxsize'] * pow(1024, isset($typeDict[$type]) ? $typeDict[$type] : 0);
    $fileInfo = $file->getInfo();
    $suffix = strtolower(pathinfo($fileInfo['name'], PATHINFO_EXTENSION));
    $suffix = $suffix ? $suffix : 'file';

    $mimetypeArr = explode(',', $upload['mimetype']);
    $typeArr = explode('/', $fileInfo['type']);
    //验证文件后缀
    if ($upload['mimetype'] !== '*' && !in_array($suffix, $mimetypeArr) && !in_array($fileInfo['type'], $mimetypeArr) && !in_array($typeArr[0] . '/*', $mimetypeArr))
    {
    $this->error(__('Uploaded file format is limited'));
    }
    $replaceArr = [
    '{year}' => date("Y"),
    '{mon}' => date("m"),
    '{day}' => date("d"),
    '{hour}' => date("H"),
    '{min}' => date("i"),
    '{sec}' => date("s"),
    '{random}' => Random::alnum(16),
    '{random32}' => Random::alnum(32),
    '{filename}' => $suffix ? substr($fileInfo['name'], 0, strripos($fileInfo['name'], '.')) : $fileInfo['name'],
    '{suffix}' => $suffix,
    '{.suffix}' => $suffix ? '.' . $suffix : '',
    '{filemd5}' => md5_file($fileInfo['tmp_name']),
    ];
    $savekey = $upload['savekey'];
    $savekey = str_replace(array_keys($replaceArr), array_values($replaceArr), $savekey);

    $uploadDir = substr($savekey, 0, strripos($savekey, '/') + 1);
    $fileName = substr($savekey, strripos($savekey, '/') + 1);
    //
    $splInfo = $file->validate(['size' => $size])->move(ROOT_PATH . '/public' . $uploadDir, $fileName);
    if ($splInfo)
    {
    $imagewidth = $imageheight = 0;
    if (in_array($suffix, ['gif', 'jpg', 'jpeg', 'bmp', 'png', 'swf']))
    {
    $imgInfo = getimagesize($splInfo->getPathname());
    $imagewidth = isset($imgInfo[0]) ? $imgInfo[0] : $imagewidth;
    $imageheight = isset($imgInfo[1]) ? $imgInfo[1] : $imageheight;
    }
    $params = array(
    'filesize' => $fileInfo['size'],
    'imagewidth' => $imagewidth,
    'imageheight' => $imageheight,
    'imagetype' => $suffix,
    'imageframes' => 0,
    'mimetype' => $fileInfo['type'],
    'url' => $uploadDir . $splInfo->getSaveName(),
    'uploadtime' => time(),
    'storage' => 'local',
    'sha1' => $sha1,
    );
    $attachment = model("attachment");
    $attachment->data(array_filter($params));
    $attachment->save();
    \think\Hook::listen("upload_after", $attachment);
    //进行身份判断 将头像 url 写入到数据库中
    if(isset($this->user['teacher_phone']))
    {
    db('teacher')->where('teacher_phone',$this->user['teacher_phone'])
    ->setField('avatar',$uploadDir . $splInfo->getSaveName());
    }
    else if (isset($this->user['parent_phone']))
    {

    db('parents')->where('parent_phone',$this->user['parent_phone'])
    ->setField('avatar',$uploadDir . $splInfo->getSaveName());
    }

    $this->success(__('Upload successful'), $attachment);
    }
    else
    {
    // 上传失败获取错误信息
    $this->error($file->getError());
    }
    }
    ```
    希望能帮到你
    Alucns
        17
    Alucns  
    OP
       2018-04-24 09:55:47 +08:00
    @dilu 谢谢!
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     822 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 26ms UTC 21:20 PVG 05:20 LAX 13:20 JFK 16:20
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86