コンポーネントの完全な混乱があります。現在、関数を渡していますが、機能させることができない数百万のことを試みています。
export default class DatafileUpload extends Component {
initialState = {
fileUploading: false,
fileList: [],
status: 'empty', // 'empty' | 'active' | 'success' | 'exception'
file: {}
}
state = this.initialState
static propTypes = {
userId: PropTypes.string.isRequired,
datasetId: PropTypes.string.isRequired
}
scrubFilename = (filename) => filename.replace(/[^\w\d_\-.]+/ig, '')
requestSignedS3Url = (file) => {
const filename = this.scrubFilename(file.name)
const params = {
userId: this.props.userId,
contentType: file.type,
Key: `${filename}`
};
return api.get('/s3/signUpload', { params })
.then(response => {
return response.data;
})
.catch(error => {
console.error(error);
});
}
uploadFile = (file) => {
this.requestSignedS3Url(file)
.then(signResult => this.uploadToS3(file, signResult))
.catch(error => console.log(error))
}
createCORSRequest = (method, url, opts) => {
opts = opts || {};
let xhr = new XMLHttpRequest();
if (xhr.withCredentials != null) {
xhr.open(method, url, true);
if (opts.withCredentials != null) {
xhr.withCredentials = opts.withCredentials;
}
} else if (typeof XDomainRequest !== "undefined") {
xhr = new XDomainRequest();
xhr.open(method, url);
} else {
xhr = null;
}
return xhr;
};
stepFunctions = () => {
return {
preprocess: (file) => {
console.log('Pre-process: ' + file.name);
},
onProgress: (percent, message, file) => {
this.setState({ fileUploading: true })
console.log('Upload progress: ' + percent + '% ' + message);
},
onFinish: (signResult) => {
this.setState({ fileUploading: false })
console.log("Upload finished: " + signResult.publicUrl)
},
onError: (message) => {
this.setState({ fileUploading: false })
console.log("Upload error: " + message);
},
scrubFilename: (filename) => {
return filename.replace(/[^\w\d_\-\.]+/ig, '');
},
onFinishS3Put: (signResult, file) => {
console.log(signResult)
return console.log('base.onFinishS3Put()', signResult.publicUrl);
}
}
}
uploadToS3 = async (file, signResult) => {
const xhr = await this.createCORSRequest('PUT', signResult.signedUrl);
const functions = this.stepFunctions()
functions.preprocess(file)
if (!xhr) {
functions.onError('CORS not supported', file);
} else {
xhr.onload = () => {
if (xhr.status === 200) {
functions.onProgress(100, 'Upload completed', file);
return functions.onFinishS3Put('potatopotato', file);
} else {
return functions.onError('Upload error: ' + xhr.status, file);
}
};
xhr.onerror = () => {
return functions.onError('XHR error', file);
};
xhr.upload.onprogress = (e) => {
let percentLoaded;
if (e.lengthComputable) {
percentLoaded = Math.round((e.loaded / e.total) * 100);
return functions.onProgress(percentLoaded, percentLoaded === 100 ? 'Finalizing' : 'Uploading', file);
}
};
}
xhr.setRequestHeader('Content-Type', file.type);
if (signResult.headers) {
const signResultHeaders = signResult.headers
Object.keys(signResultHeaders).forEach(key => {
const val = signResultHeaders[key];
xhr.setRequestHeader(key, val);
})
}
xhr.setRequestHeader('x-amz-acl', 'public-read');
this.httprequest = xhr;
return xhr.send(file);
};
handleChange = ({ file, fileList }) => {
const functions = this.stepFunctions()
functions.preprocess(file)
if (!file) {
functions.onError('CORS not supported', file);
} else {
file.onload = () => {
if (file.status === 200) {
functions.onProgress(100, 'Upload completed', file);
return functions.onFinishS3Put('potatopotato', file);
} else {
return functions.onError('Upload error: ' + file.status, file);
}
};
file.onerror = () => {
return functions.onError('XHR error', file);
};
file.upload.onprogress = (e) => {
let percentLoaded;
if (e.lengthComputable) {
percentLoaded = Math.round((e.loaded / e.total) * 100);
return functions.onProgress(percentLoaded, percentLoaded === 100 ? 'Finalizing' : 'Uploading', file);
}
};
}
console.log('File: ', file)
// always setState
this.setState({ fileList });
}
render() {
const props = {
onChange: this.handleChange,
multiple: true,
name: "uploadFile",
defaultFileList: this.initialState.fileList,
data: this.uploadFile,
listType: "text",
customRequest: ????,
showUploadList: {
showPreviewIcon: true,
showRemoveIcon: true
},
onProgress: ( {percent} ) => {
this.setState({ fileUploading: true })
console.log('Upload progress: ' + percent + '% ' );
},
onError: (error, body) => {
this.setState({ fileUploading: false })
console.log("Upload error: " + error);
},
onSuccess: (body)=> {
console.log(body)
return console.log('base.onFinishS3Put()');
}
};
return (
<Upload {...props} fileList={this.state.fileList}>
<Button>
<Icon type="upload" /> Upload
</Button>
</Upload>
)
}
}
私はこのコードが意味をなさない混乱であることを知っており、データがすべて重複しています。私はそれがそれを機能させて、それからクリーンアップ/最適化したいです。基本的に、コンポーネントの進行状況バーを更新したり、onChange
を使用したり、customRequest
を使用しようとしたりすることはできません。 customRequest
はいつ呼び出されますか? これ は説明があまり豊富ではありません... Ajaxアップロードの置き換えをどのように行うのかわかりません。
私もそれに苦労していて、あなたの質問を見つけました。
したがって、customRequestとonChangeを使用する方法は次のとおりです。
<Upload name="file" customRequest={this.customRequest} onChange={this.onChange}>
<Button>
<Icon type="upload" /> Click to Upload
</Button>
</Upload>
...
onChange = (info) => {
const reader = new FileReader();
reader.onloadend = (obj) => {
this.imageDataAsURL = obj.srcElement.result;
};
reader.readAsDataURL(info.file.originFileObj);
...
};
...
customRequest = ({ onSuccess, onError, file }) => {
const checkInfo = () => {
setTimeout(() => {
if (!this.imageDataAsURL) {
checkInfo();
} else {
this.uploadFile(file)
.then(() => {
onSuccess(null, file);
})
.catch(() => {
// call onError();
});
}
}, 100);
};
checkInfo();
};
おそらくもっと良い方法がありますが、それがあなたを助けることを願っています。
私はそれをかなり苦労し、このケースを処理する効率的な方法を見つけました。
最初に、本文とリクエストタイプに変更する必要がある場合にのみ、customRequestをいじる必要があります(「put」の代わりにpostを使用するか、xmlを使用するか、別のヘッダーを追加するなど)。
署名するURLの場合、次のようにアップロードするための適切なURLを持つpromiseを返すアクションプロップコールバックで送信できます。
handleUplaod = (file: any) => {
return new Promise(async (resolve, reject) => {
const fileName = `nameThatIwant.type`;
const url = await S3Fetcher.getPresignedUrl(fileName);
resolve(url);
});
次のようにレンダリングします:
render(){
return(
....
<Upload
action={this.handleUplaod}
....
Upload>
アップローダーはアクションプロップからURLを取得します。
提供されているonChangeメソッドも、アップロードのステータスが変更されるたびに呼び出されます-
onChange#この関数は、アップロードが進行中、完了、または失敗したときに呼び出されます。
状態変更をアップロードすると、次が返されます。
{file:{/ * ... /}、fileList:[/ ... /]、event:{/ ... * /}、}
アップロードが始まったら、そこからファイルリーダーをアクティブにする必要があります。お気に入り:
....
fileReader = new FileReader();
.....
onChange = (info) => {
if (!this.fileReader.onloadend) {
this.fileReader.onloadend = (obj) => {
this.setState({
image: obj.srcElement.result, //will be used for knowing load is finished.
});
};
// can be any other read function ( any reading function from
// previously created instance can be used )
this.fileReader.readAsArrayBuffer(info.file.originFileObj);
}
};
ステージが完了すると、event = undefindであることに注意してください
アップロードイベントからUIを更新するには、customRequestのオプション変数を使用して、必要なときにいつでも呼び出す必要があります。
アップロードが完了するとonSuccess-が呼び出され、読み込みアイコンがファイル名に変わります。
onError-は、ファイルされたファイル名を赤にペイントします。
onProgress-は進行状況バーを更新するため、更新する場合は{percent:[NUMBER]}で呼び出す必要があります。
たとえば私のコードでは
customRequest = async option => {
const { onSuccess, onError, file, action, onProgress } = option;
const url = action;
await new Promise(resolve => this.waitUntilImageLoaded(resolve)); //in the next section
const { image } = this.state; // from onChange function above
const type = 'image/png';
axios
.put(url, Image, {
onUploadProgress: e => {
onProgress({ percent: (e.loaded / e.total) * 100 });
},
headers: {
'Content-Type': type,
},
})
.then(respones => {
/*......*/
onSuccess(respones.body);
})
.catch(err => {
/*......*/
onError(err);
});
};
waitUntilImageLoaded = resolve => {
setTimeout(() => {
this.state.image
? resolve() // from onChange method
: this.waitUntilImageLoaded(resolve);
}, 10);
};
私はaxiosを使用しましたが、他のライブラリも使用でき、最も重要な部分-
render(){
return(
....
<Upload
onChange={this.onChange}
customRequest={this.customRequest}
...>
onCustomRequest = file => {
return new Promise(((resolve, reject) => {
const ajaxResponseWasFine = true;
setTimeout(() => {
if (ajaxResponseWasFine) {
const reader = new FileReader();
reader.addEventListener('load', () => {
resolve(reader.result);
}, false);
if (file) {
reader.readAsDataURL(file);
}
} else {
reject('error');
}
}, 1000);
}));
};
<Dragger
action={this.onCustomRequest}
fileList={fileList}
onChange={this.handleChangeUpload}
className={styles.dragWrapper}
showUploadList={true}
beforeUpload={this.beforeUpload}
>